#include "smelter_screen.h"
#include "helper.h"
#include "debug.h"

/*空闲5分钟未收到新包,回到默认模式*/
#define MAX_SCREEN_IDEL (10000)
#define NOPACK_EFFECT 333
typedef struct
{
    su16 idelCount;
    su16 colorSum;
    su8 usedDots;                             //共使用了几个点？
    su8 usedDotOffset[MAX_MODE_SCREEN_DOT];   //几个点的偏移原点的位置
    su8 usedDotBufIndex[MAX_MODE_SCREEN_DOT]; //点在使用的寄存器的位置的编号
    Helper_EaseInEaseOut_Context EaseR[MAX_MODE_SCREEN_DOT];
    Helper_EaseInEaseOut_Context EaseG[MAX_MODE_SCREEN_DOT];
    Helper_EaseInEaseOut_Context EaseB[MAX_MODE_SCREEN_DOT];
    SF_Boolen isIdelDirCCW;
    su8 brightness[MAX_MODE_SCREEN_DOT];
} Smelter_Screen_Context;
static Smelter_Screen_Context context;

void smelter_screen_restart(Config_Mode_Screen *screen)
{
    su16 tmp;
    context.idelCount = 0;
    context.usedDots = 0;
    context.isIdelDirCCW = SF_True;
    for (tmp = 0; tmp < MAX_MODE_SCREEN_DOT; tmp++)
    {
        context.EaseR[tmp].key = 0;
        context.EaseG[tmp].key = 0;
        context.EaseB[tmp].key = 0;
        context.EaseR[tmp].target = 0;
        context.EaseG[tmp].target = 0;
        context.EaseB[tmp].target = 0;

        context.brightness[tmp] = 0xFF;
    }
    //update realParms
    DPRINT(DEBUG_INFO, "[SMELTER SCREEN]:");
    for (tmp = 0; tmp < 8; tmp++)
    {
        if (((su8)(gCfgModeFactoryPtr->mode_screen_hiddenMask & (1 << tmp)))!=0)
        {
            continue;
        }
        context.usedDotOffset[context.usedDots] = helper_cacl_precentage_denoinator255(gCfgFactoryPtr->enabledDotNumber, gCfgModeFactoryPtr->mode_screen_offsetRef[tmp]);
        context.usedDotBufIndex[context.usedDots] = tmp;
        DPRINT(DEBUG_INFO, "%d, ", context.usedDotOffset[context.usedDots]);
        context.usedDots++;
    }
    DPRINT(DEBUG_INFO, "\r\n");
}

su16 smelter_ColorSum(Config_Mode_Screen *screen)
{
    su16 sum = 0;
    su16 ii = 0;
    su8 index = 0;
    for (ii = 0; ii < context.usedDots; ii++)
    {
        index = context.usedDotBufIndex[ii];
        sum = sum + screen->dot[index].R + screen->dot[index].G + screen->dot[index].B;
    }
    return sum;
}

Efct_Stage smelter_screen_process(Config_Mode_Screen *screen)
{
    su16 tmp;
    su16 tmp1;
    su16 tmp2;
    su16 posErr;
    su8 ofst1;
    su8 ofst2;
    Color A;
    Color B;
    SF_Boolen isIdel = SF_False;
    SF_Boolen isShowNoPackEffect = SF_False;

    if (context.usedDots == 0)
    {
        return E_FINISHED;
    }

    tmp = smelter_ColorSum(screen);
    if (tmp != context.colorSum)
    {
        isIdel = SF_False;
        //reset timer
        context.idelCount = 0;
        context.colorSum = tmp;
    }
    else
    {
        if (context.idelCount >= MAX_SCREEN_IDEL)
        {
            isIdel = SF_True;
        }
        else
        {
            context.idelCount++;
            if (context.idelCount > NOPACK_EFFECT)
            {
                isShowNoPackEffect = SF_True;
            }
        }
    }

    if (isShowNoPackEffect == SF_True)
    {
        //todo
        for (tmp = 0; tmp < context.usedDots; tmp++)
        {
            if (context.isIdelDirCCW)
            {
                if (context.brightness[tmp] <= 100)
                {
                    context.isIdelDirCCW = SF_False;
                }
                else
                {
                    context.brightness[tmp]-=2;
                }
            }
            else
            {
                if (context.brightness[tmp] >= 240)
                {
                    context.isIdelDirCCW = SF_True;
                }
                else
                {
                    context.brightness[tmp]+=2;
                }
            }

            context.EaseR[tmp].key = helper_cacl_precentage_denoinator255(context.EaseR[tmp].target, context.brightness[tmp]);
            context.EaseG[tmp].key = helper_cacl_precentage_denoinator255(context.EaseG[tmp].target, context.brightness[tmp]);
            context.EaseB[tmp].key = helper_cacl_precentage_denoinator255(context.EaseB[tmp].target, context.brightness[tmp]);
        }
    }
    else
    {
        
        for (tmp = 0; tmp < context.usedDots; tmp++)
        {
            context.brightness[tmp] = 255;
            context.EaseR[tmp].target = screen->dot[context.usedDotBufIndex[tmp]].R;
            context.EaseG[tmp].target = screen->dot[context.usedDotBufIndex[tmp]].G;
            context.EaseB[tmp].target = screen->dot[context.usedDotBufIndex[tmp]].B;
            helper_easeInEaseOutGenerate(&context.EaseR[tmp]);
            helper_easeInEaseOutGenerate(&context.EaseG[tmp]);
            helper_easeInEaseOutGenerate(&context.EaseB[tmp]);
        }
    }

    //填充 0~1 1~2 2~3 3~4 4~5 5~6 6~7
    for (tmp = 0; tmp < (context.usedDots - 1); tmp++)
    {
        ofst1 = context.usedDotOffset[tmp];
        ofst2 = context.usedDotOffset[tmp + 1];

        A.R = context.EaseR[tmp].key;
        A.G = context.EaseG[tmp].key;
        A.B = context.EaseB[tmp].key;

        B.R = context.EaseR[tmp + 1].key;
        B.G = context.EaseG[tmp + 1].key;
        B.B = context.EaseB[tmp + 1].key;

        posErr = helper_absErr(ofst1, ofst2);

        for (tmp1 = 0; tmp1 < posErr; tmp1++)
        {
            rgbStrip.colors[ofst1 + tmp1].R = helper_colorMix(A.R, B.R, posErr, tmp1);
            rgbStrip.colors[ofst1 + tmp1].G = helper_colorMix(A.G, B.G, posErr, tmp1);
            rgbStrip.colors[ofst1 + tmp1].B = helper_colorMix(A.B, B.B, posErr, tmp1);
        }
    }

    tmp = context.usedDots - 1;

    A.R = context.EaseR[tmp].key;
    A.G = context.EaseG[tmp].key;
    A.B = context.EaseB[tmp].key;

    B.R = context.EaseR[0].key;
    B.G = context.EaseG[0].key;
    B.B = context.EaseB[0].key;

    ofst1 = context.usedDotOffset[0];
    posErr = helper_absErr(0, ofst1);
    ofst1 = context.usedDotOffset[context.usedDots - 1];
    posErr += helper_absErr(ofst1, gCfgFactoryPtr->enabledDotNumber);

    for (tmp1 = 0; tmp1 < posErr; tmp1++)
    {
        rgbStrip.colors[(ofst1 + tmp1) % gCfgFactoryPtr->enabledDotNumber].R = helper_colorMix(A.R, B.R, posErr, tmp1);
        rgbStrip.colors[(ofst1 + tmp1) % gCfgFactoryPtr->enabledDotNumber].G = helper_colorMix(A.G, B.G, posErr, tmp1);
        rgbStrip.colors[(ofst1 + tmp1) % gCfgFactoryPtr->enabledDotNumber].B = helper_colorMix(A.B, B.B, posErr, tmp1);
    }

    if (isIdel)
    {
        return E_FINISHED;
    }
    else
    {
        return E_PROCESS;
    }
}